package openase.audiosearch.ranking;

import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.Map.Entry;

import openase.audio.AudioFingerprint;
import openase.audio.AudioInfo;
import openase.audiosearch.FingerprintMatch;

import org.apache.commons.collections.Bag;
import org.apache.commons.collections.bag.HashBag;


public class SameDeltaOffsetsOfMatchesRankingStrategy implements RankingStrategy {

    @Override
    public AudioRanking rank(FingerprintMatch[] matchingFps) {
        Map<AudioInfo, List<FingerprintMatch>> map = new HashMap<AudioInfo, List<FingerprintMatch>>();
        
        for (FingerprintMatch match : matchingFps) {
            add(map, match.getRepositoryFingerprint().getSource(), match);
        }
        
        final AudioRankingBuilder builder = new AudioRankingBuilder();
        
        for (Entry<AudioInfo, List<FingerprintMatch>> entry : map.entrySet()) {
            AudioInfo audio = entry.getKey();
            List<FingerprintMatch> matches = entry.getValue();
            
            // the biggest amount of equal delta of offsets found
            int max = 0;
            
            Bag bag = new HashBag();
            for (FingerprintMatch match : matches) {
                AudioFingerprint queryFp = match.getQueryFingerprint();
                AudioFingerprint repositoryFp = match.getRepositoryFingerprint();
                
                // computes the difference
                int deltaOffset = repositoryFp.getOffset() - queryFp.getOffset();
                
                bag.add(deltaOffset);
                max = Math.max(max, bag.getCount(deltaOffset));
            }
            
            builder.add(audio, max);
        }
        
        return builder.getAudioRanking();
    }
    
    private static void add(Map<AudioInfo, List<FingerprintMatch>> map, AudioInfo source, FingerprintMatch match) {
        List<FingerprintMatch> list = map.get(source);
        if (list == null) {
            list = new ArrayList<FingerprintMatch>();
            map.put(source, list);
        }
        list.add(match);
    }

}
